From 6f4cfdc70138fdcc20e614bbdab6d542f72ee377 Mon Sep 17 00:00:00 2001 From: oliskoli Date: Mon, 20 Aug 2007 21:27:40 +0000 Subject: [PATCH] xol: Add support for Swiss Map 50 'xol' format. --- xol.c | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 xol.c diff --git a/xol.c b/xol.c new file mode 100644 index 000000000..4075bf980 --- /dev/null +++ b/xol.c @@ -0,0 +1,350 @@ +/* + + Support for Swiss Map 50 (.xol) format + + Copyright (C) 2007 Olaf Klein, o.b.klein@gpsbabel.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + +*/ + +#include "defs.h" +#include "xmlgeneric.h" +#include "jeeps/gpsmath.h" +#include "garmin_tables.h" + +static waypoint *wpt; +static route_head *trk; +static gbfile *fout; +static int space; +static bounds all_bounds; +static short_handle short_h; + +static arglist_t xol_args[] = +{ + ARG_TERMINATOR +}; + +#define MYNAME "xol" + +#if ! HAVE_LIBEXPAT +void +xol_rd_init(const char *fname) +{ + fatal(MYNAME ": This build excluded \"" MYNAME "\" support because expat was not installed.\n"); +} + +void +xol_read(void) +{ +} + +#else + +static xg_callback xol_shape, xol_shape_end; +static xg_callback xol_waypt, xol_overlay; + +#define XOL "/overlays/overlay" + +static +xg_tag_mapping xol_map[] = { + { xol_overlay, cb_start, XOL }, + { xol_shape, cb_start, XOL "/shapes/*shape" }, + { xol_shape_end, cb_end, XOL "/shapes/*shape" }, + { xol_waypt, cb_start, XOL "/shapes/shape/*points/point" }, + { NULL, 0, NULL } +}; + + +static void +xol_overlay(const char *args, const char **attrv) +{ + const char **avp = &attrv[0]; + + while (*avp) { + if (strcmp(avp[0], "version") == 0) { + if (strcmp(avp[1], "1.0") != 0) + fatal(MYNAME ": Unsupported version %s.\n", avp[1]); + } + + avp+=2; + } +} + +static void +xol_shape(const char *args, const char **attrv) +{ + const char **avp = &attrv[0]; + + while (*avp) { + if (strcmp(avp[0], "type") == 0) { + if (strcmp(avp[1], "waypoint") == 0) { + wpt = waypt_new(); + } + else if (strcmp(avp[1], "polyline") == 0) { + trk = route_head_alloc(); + track_add_head(trk); + } + } + else if (strcmp(avp[0], "name") == 0) { + if (wpt) wpt->shortname = xstrdup(avp[1]); + else if (trk) trk->rte_name = xstrdup(avp[1]); + } + else if (strcmp(avp[0], "comment") == 0) { + if (wpt) wpt->notes = xstrdup(avp[1]); + } + else if (strcmp(avp[0], "alt") == 0) { + if (wpt) wpt->altitude = atof(avp[1]); + } + else if (strcmp(avp[0], "timestamp") == 0) { + if (wpt) wpt->creation_time = xml_parse_time(avp[1], &wpt->microseconds); + } + else if (strcmp(avp[0], "icon") == 0) { + if (wpt) { + wpt->icon_descr = xstrdup(avp[1]); + wpt->wpt_flags.icon_descr_is_dynamic = 1; + } + } + + avp+=2; + } +} + +static void +xol_shape_end(const char *args, const char **unused) +{ + if (wpt) { + if (trk) track_add_wpt(trk, wpt); + else waypt_add(wpt); + wpt = NULL; + } + else if (trk) { + if (trk->rte_waypt_ct == 0) track_del_head(trk); + trk = NULL; + } +} + +static void +xol_waypt(const char *args, const char **attrv) { + const char **avp = &attrv[0]; + int x, y; + + while (*avp) { + if (strcmp(avp[0], "y") == 0) + y = atoi(avp[1]); + else if (strcmp(avp[0], "x") == 0) + x = atoi(avp[1]); + avp+=2; + } + + GPS_Math_CH1903_NGEN_To_WGS84((double)x, (double)y, &wpt->latitude, &wpt->longitude); +} + +static void +xol_rd_init(const char *fname) +{ + trk = NULL; + wpt = NULL; + + xml_init(fname, xol_map, NULL); +} + +static void +xol_read(void) +{ + xml_read(); +} + +#endif + +static void +xol_rd_deinit(void) +{ + xml_deinit(); +} + +/* writer */ + +static void +xol_fatal_outside(const waypoint *wpt) +{ + gbfprintf(fout, "#####\n"); + fatal(MYNAME ": %s (%s) is outside of convertable area \"%s\"!\n", + wpt->shortname ? wpt->shortname : "Waypoint", + pretty_deg_format(wpt->latitude, wpt->longitude, 'd', NULL, 0), + gt_get_mps_grid_longname(grid_swiss, MYNAME)); +} + + +static void +xol_write_time(const waypoint *wpt) +{ + char time_string[64]; + + xml_fill_in_time(time_string, wpt->creation_time, wpt->microseconds, XML_LONG_TIME); + if (time_string[0]) { + gbfprintf(fout, " timestamp=\"%s\"", time_string); + } +} + +static void +xol_write_string(const char *name, const char *str) +{ + if (str && *str) { + char *temp = strenquote(str, '"'); + gbfprintf(fout, " %s=%s", name, temp); + xfree(temp); + } +} + +static void +xol_waypt_bound_calc(const waypoint *wpt) +{ + waypt_add_to_bounds(&all_bounds, wpt); +} + +static void +xol_wr_init(const char *fname) +{ + fout = gbfopen(fname, "w", MYNAME); + + space = 1; + waypt_init_bounds(&all_bounds); + short_h = mkshort_new_handle(); + + setshort_length(short_h, 1024); /* ??? */ + setshort_badchars(short_h, "\r\n\t"); + setshort_mustupper(short_h, 0); + setshort_mustuniq(short_h, 1); + setshort_whitespace_ok(short_h, 1); + setshort_repeating_whitespace_ok(short_h, 1); + setshort_defname(short_h, "Waypoint"); +} + +static void +xol_wr_deinit(void) +{ + mkshort_del_handle(&short_h); + gbfclose(fout); +} + +static void +xol_waypt_disp_cb(const waypoint *wpt) +{ + double x, y; + char *name; + + name = wpt->shortname; + if ((name == NULL) || (*name == '\0') || global_opts.synthesize_shortnames) + name = mkshort_from_wpt(short_h, wpt); + else + name = mkshort(short_h, name); + + if (! GPS_Math_WGS84_To_CH1903_NGEN(wpt->latitude, wpt->longitude, &x, &y)) + xol_fatal_outside(wpt); + + gbfprintf(fout, "%*snotes); + xol_write_string("icon", wpt->icon_descr); + if (wpt->creation_time) xol_write_time(wpt); + if (wpt->altitude != unknown_alt) gbfprintf(fout, " alt=\"%.f\"", wpt->altitude); + gbfprintf(fout, ">\n"); + + gbfprintf(fout, "%*s\n", space++*2, ""); + gbfprintf(fout, "%*s\n", space*2, "", x, y); + gbfprintf(fout, "%*s\n", --space*2, ""); + gbfprintf(fout, "%*s\n", --space*2, ""); + + xfree(name); +} + +static void +xol_track_hdr_disp_cb(const route_head *trk) +{ + gbfprintf(fout, "%*srte_name); + gbfprintf(fout, " lineSize=\"3\" lineColor=\"#e60000\" lineStyle=\"solid\">\n"); + gbfprintf(fout, "%*s\n", space++*2, ""); +} + +static void +xol_track_tlr_disp_cb(const route_head *trk) +{ + gbfprintf(fout, "%*s\n", --space*2, ""); + gbfprintf(fout, "%*s\n", --space*2, ""); +} + +static void +xol_trkpt_disp_cb(const waypoint *wpt) +{ + double x, y; + + if (! GPS_Math_WGS84_To_CH1903_NGEN(wpt->latitude, wpt->longitude, &x, &y)) + xol_fatal_outside(wpt); + + gbfprintf(fout, "%*screation_time) xol_write_time(wpt); + if (wpt->altitude != unknown_alt) gbfprintf(fout, " alt=\"%.f\"", wpt->altitude); + gbfprintf(fout, ">\n"); + gbfprintf(fout, "%*s\n", space++*2, ""); + gbfprintf(fout, "%*s\n", space*2, "", x, y); + gbfprintf(fout, "%*s\n", --space*2, ""); + gbfprintf(fout, "%*s\n", --space*2, ""); +} + +static void +xol_write(void) +{ + double x, y; + + waypt_disp_all(xol_waypt_bound_calc); + track_disp_all(NULL, NULL, xol_waypt_bound_calc); + + if (! GPS_Math_WGS84_To_CH1903_NGEN( + (all_bounds.min_lat + all_bounds.max_lat) / 2, + (all_bounds.min_lon + all_bounds.max_lon) / 2, &x, &y)) { + gbfprintf(fout, "#####\n"); + fatal(MYNAME ": At least one point is outside of convertable area \"%s\"!\n", + gt_get_mps_grid_longname(grid_swiss, MYNAME)); + } + + gbfprintf(fout, "\n", global_opts.charset_name); + gbfprintf(fout, "\n"); + gbfprintf(fout, "%*s\n", space++*2, ""); + gbfprintf(fout, "%*s
\n", space*2, "", x, y); + gbfprintf(fout, "%*s\n", space++*2, ""); + waypt_disp_all(xol_waypt_disp_cb); + track_disp_all(xol_track_hdr_disp_cb, xol_track_tlr_disp_cb, xol_trkpt_disp_cb); + gbfprintf(fout, "%*s\n", --space*2, ""); + gbfprintf(fout, "%*s\n", --space*2, ""); + gbfprintf(fout, "\n"); +} + +ff_vecs_t xol_vecs = { + ff_type_file, + { ff_cap_read | ff_cap_write, /* waypoints */ + ff_cap_read | ff_cap_write, /* tracks */ + ff_cap_none }, /* routes */ + xol_rd_init, + xol_wr_init, + xol_rd_deinit, + xol_wr_deinit, + xol_read, + xol_write, + NULL, + xol_args, + CET_CHARSET_UTF8, 0 +}; -- 2.30.2